1 00:00:00,740 --> 00:00:06,050 Alrighty, to get started with the story section of our game, we need to create the loading screen 2 00:00:06,050 --> 00:00:09,740 and the scripts that will load all of the modules on the client and on the server. 3 00:00:09,740 --> 00:00:14,780 So before we get started real quick, let's go ahead and move our Squidward AI back into server storage 4 00:00:14,780 --> 00:00:16,130 because we don't need him for now. 5 00:00:16,130 --> 00:00:21,500 We'll be scripting him later, but thankfully we did most of the hard work already when we scripted 6 00:00:21,500 --> 00:00:26,360 all of the loading functionality on our lobby, so we can literally just copy the scripts from our lobby 7 00:00:26,360 --> 00:00:31,310 and use those loaders for our loading screen and all the other stuff here in the story section of our 8 00:00:31,310 --> 00:00:31,850 game. 9 00:00:31,850 --> 00:00:37,160 So here inside of our lobby section, I'm literally just going to go into replicated first into starter 10 00:00:37,160 --> 00:00:41,060 player scripts and as well in server script service. 11 00:00:41,060 --> 00:00:44,270 And I'm going to just copy all of these scripts here. 12 00:00:44,270 --> 00:00:45,830 Control C that. 13 00:00:45,830 --> 00:00:50,000 And now back in our main game, I'm just going to paste those scripts in the lobby for now, because 14 00:00:50,000 --> 00:00:55,430 we're just going to go ahead and copy all of the code that we have in here and use it for the same loaders 15 00:00:55,430 --> 00:00:56,750 on the server as well. 16 00:00:56,750 --> 00:01:02,330 So we can paste that for the server in there for our loading guy, we can just copy all of this, go 17 00:01:02,330 --> 00:01:06,470 into replicated first and use that for our loading guy. 18 00:01:07,050 --> 00:01:10,740 And then lastly, we can do the same thing for loading all of these scripts on the client. 19 00:01:10,740 --> 00:01:17,310 So we'll just copy all of that, go to startup player scripts and use that for our start script on the 20 00:01:17,310 --> 00:01:18,060 client. 21 00:01:19,270 --> 00:01:22,600 Now there is a few changes that we'll want to make in our loading GUI. 22 00:01:22,630 --> 00:01:28,240 So when we go back into our loading GUI handler is that I want to make a new constant for waiting for 23 00:01:28,240 --> 00:01:33,400 other players, because we're not going to start the story of our horror game until all of the players 24 00:01:33,400 --> 00:01:34,840 in our game have loaded in. 25 00:01:34,840 --> 00:01:36,490 So I'm going to create a new wait text. 26 00:01:36,490 --> 00:01:42,700 I'm going to call it wait, uh, text players or we can call it wait for players. 27 00:01:42,700 --> 00:01:43,480 Let's do that instead. 28 00:01:43,480 --> 00:01:49,390 Wait for players and we'll set the text equal to waiting for players. 29 00:01:50,200 --> 00:01:55,300 And then what we could do is we could scroll down and once our client has finished loading, what we 30 00:01:55,300 --> 00:01:57,910 could do here is we could create another while loop. 31 00:01:57,910 --> 00:02:02,800 So I'm going to use task dot spawn to spawn this while loop in a new thread. 32 00:02:03,010 --> 00:02:07,990 And what we're going to do is we're going to basically do the exact same thing that we've done up here, 33 00:02:08,260 --> 00:02:12,550 but instead we're going to set the text equal to wait for players. 34 00:02:17,420 --> 00:02:23,150 And then outside of this loop, what we're going to do is we're going to make a reference to that event 35 00:02:23,150 --> 00:02:24,980 we have in replicated storage. 36 00:02:24,980 --> 00:02:30,560 So inside of replicated storage in events underneath remotes, we have a player loaded remote event. 37 00:02:30,560 --> 00:02:35,240 And the plan is, is that when our client finishes loading, we're going to fire to the server to let 38 00:02:35,240 --> 00:02:36,740 the server know that we finished loading. 39 00:02:36,740 --> 00:02:41,510 And then once all of the players have loaded, then the server is going to fire this event back to all 40 00:02:41,510 --> 00:02:46,220 of the clients to let them know that, you know, everybody has loaded into the game. 41 00:02:46,280 --> 00:02:48,770 So we'll just make a quick reference to this event real quick. 42 00:02:48,770 --> 00:02:53,360 I'll just call it player loaded event equal to replicated storage. 43 00:02:56,940 --> 00:02:58,110 Events. 44 00:02:59,390 --> 00:03:01,880 Dot remotes, dot player loaded. 45 00:03:01,880 --> 00:03:05,390 And I believe we're going to have to make a reference to replicated storage up here. 46 00:03:05,390 --> 00:03:06,740 So let's do that real quick. 47 00:03:11,990 --> 00:03:17,750 And do note that I do not have to wait for any of these children here, because we wait for the entire 48 00:03:17,750 --> 00:03:19,790 game to load above up here. 49 00:03:19,790 --> 00:03:22,610 So this stuff is guaranteed to be inside of replicated storage. 50 00:03:22,610 --> 00:03:23,930 We don't have to wait for it. 51 00:03:24,500 --> 00:03:28,040 So once we have finished loading, then what we're going to do is we're going to reference our player 52 00:03:28,040 --> 00:03:30,830 loaded event and fire to the server that we have finished loading. 53 00:03:31,520 --> 00:03:39,410 And then we're going to access this event again and wait for the on client event script signal to get 54 00:03:39,410 --> 00:03:39,800 fired. 55 00:03:39,800 --> 00:03:41,270 And we're just going to wait for this. 56 00:03:41,270 --> 00:03:45,350 So this will let us know when all of the players in our game has loaded. 57 00:03:45,350 --> 00:03:50,630 So fires when all players are loaded in the game. 58 00:03:51,210 --> 00:03:55,860 And then finally, once all of the players have loaded into the game, then we can fade out our loading 59 00:03:55,860 --> 00:03:56,430 screen. 60 00:03:57,000 --> 00:04:02,010 Now to actually see all this working, we're going to have to fill out another service inside of the 61 00:04:02,010 --> 00:04:02,610 server. 62 00:04:02,610 --> 00:04:06,210 And that service is going to be when a player joins our game. 63 00:04:06,210 --> 00:04:08,910 So we're going to open up our player join service here. 64 00:04:08,910 --> 00:04:10,950 And we're going to go ahead and fill this out. 65 00:04:10,980 --> 00:04:16,020 So we're going to go ahead and call this service player joined service. 66 00:04:16,020 --> 00:04:19,560 And we'll make sure to return it at the end of this module script. 67 00:04:20,190 --> 00:04:22,470 And we're only going to need three services in here. 68 00:04:22,470 --> 00:04:24,840 One is going to be the player service, of course. 69 00:04:25,770 --> 00:04:28,530 We're going to need server storage. 70 00:04:31,350 --> 00:04:34,110 And then we're going to need replicated storage. 71 00:04:37,530 --> 00:04:42,000 Now, inside of our variables section, we need to make references to several events. 72 00:04:42,030 --> 00:04:46,320 One event is called uh Start Game which is in server storage. 73 00:04:46,320 --> 00:04:48,630 So we can call this start game. 74 00:04:48,630 --> 00:04:55,890 Event is equal to server storage dot events dot bind dot start game. 75 00:04:55,890 --> 00:05:00,300 So when all of our players have loaded into the game and they've notified the server that they have 76 00:05:00,300 --> 00:05:05,190 loaded, then we're going to fire this event to let the server know or to let the script that's going 77 00:05:05,190 --> 00:05:11,910 to handle running the game, you know, start the game, and then we're going to have a reference to 78 00:05:11,910 --> 00:05:13,290 the player loaded event. 79 00:05:13,290 --> 00:05:18,180 So that's in replicated storage dot events dot remotes dot player loaded. 80 00:05:20,370 --> 00:05:24,330 We're also going to have a reference to an event called, uh, update Guy. 81 00:05:24,330 --> 00:05:29,730 And we're going to use this event to tell the players to update specific elements on their guy. 82 00:05:29,730 --> 00:05:36,840 So we could call it update Guy event equal to replicated storage, dot events, dot remotes, dot update 83 00:05:36,840 --> 00:05:37,770 guy. 84 00:05:38,330 --> 00:05:44,360 And since we're going to be using remote events to give specific actions to players about updating their 85 00:05:44,360 --> 00:05:50,690 GUI, we should create our own custom enum with different commands or different actions that we must 86 00:05:50,690 --> 00:05:52,520 give to the players. 87 00:05:52,520 --> 00:05:58,490 So actually inside of replicated storage, there's a section of module scripts in here with uh custom 88 00:05:58,490 --> 00:05:59,630 enumerated types. 89 00:05:59,630 --> 00:06:02,570 And we have a GUI actions enum in here. 90 00:06:02,570 --> 00:06:08,330 So we should go ahead and fill this out to, you know, show all of the different actions that the server 91 00:06:08,330 --> 00:06:11,900 may want the client to do on their end with their GUIs. 92 00:06:12,080 --> 00:06:15,140 So we can go ahead and create a table called enum. 93 00:06:15,920 --> 00:06:19,850 And inside of this table we can go ahead and fill out many different actions. 94 00:06:19,850 --> 00:06:25,730 So for example, maybe one action the server wants the player to do is to update an objective on their 95 00:06:25,730 --> 00:06:26,150 screen. 96 00:06:26,150 --> 00:06:30,410 So we could call this update objectives. 97 00:06:31,630 --> 00:06:33,940 Equal to update objectives. 98 00:06:34,060 --> 00:06:39,100 We could have a command to tell a player that they've fulfilled a particular objective, so we could 99 00:06:39,100 --> 00:06:41,260 call it objective fulfilled. 100 00:06:44,190 --> 00:06:48,060 We could tell a player that they may be failed an objective. 101 00:06:48,060 --> 00:06:50,790 So maybe there is an objective with a time limit. 102 00:06:50,790 --> 00:06:54,420 If they fail that objective, then we want to tell them that they failed it. 103 00:06:54,420 --> 00:06:58,500 So objective failed is equal to objective failed. 104 00:06:59,070 --> 00:07:05,310 We may want to have an action to tell the player to update a particular task on their, uh, guy. 105 00:07:05,310 --> 00:07:09,390 So if you remember, when we were turning through that guy, there was a section for tasks. 106 00:07:09,390 --> 00:07:14,370 So we're going to call this update tasks is equal to update Tasks. 107 00:07:14,370 --> 00:07:18,570 This is for them to show all the tasks they need to fulfill on their screens. 108 00:07:18,570 --> 00:07:21,990 And then we're also going to have another one just called Update Task. 109 00:07:21,990 --> 00:07:24,990 And this one's going to be for updating a particular task. 110 00:07:24,990 --> 00:07:28,710 So for example, maybe one of the tasks is that you have to clean out the toilets. 111 00:07:28,710 --> 00:07:30,180 And there's three toilets to clean. 112 00:07:30,180 --> 00:07:35,430 Well when a player cleans one of them then we want to update that task and show a different, uh, number 113 00:07:35,430 --> 00:07:38,460 count for how many tasks are left to fulfill. 114 00:07:39,030 --> 00:07:43,650 And then once a task actually gets completely fulfilled, we can give them an action to do that. 115 00:07:43,650 --> 00:07:45,810 So we could call this task fulfilled. 116 00:07:48,730 --> 00:07:54,610 Another action we may want to do is to tell a player to add an objective on their screen, so we could 117 00:07:54,610 --> 00:07:58,990 call it add objective equal to add objective. 118 00:08:00,700 --> 00:08:04,720 Uh, another action we may want to do is to display that little message at the bottom of the screen 119 00:08:04,720 --> 00:08:06,700 to give the player a little bit of information. 120 00:08:06,700 --> 00:08:09,280 So we could call this small message. 121 00:08:12,110 --> 00:08:16,580 Another action we could do is to display that countdown on their screen. 122 00:08:16,580 --> 00:08:21,380 So when we have a section that's timed and we need to tick down the counter on the player's end, we 123 00:08:21,380 --> 00:08:28,220 can fire an event to the player every second and we can call it something like update countdown. 124 00:08:31,620 --> 00:08:36,690 We may want to have an action for perhaps controlling different frames. 125 00:08:36,690 --> 00:08:43,140 So for example, when the task section is over in our story, either all the players completed all the 126 00:08:43,140 --> 00:08:49,170 tasks or all the players failed to complete the tasks within the time limit, then we need to go ahead 127 00:08:49,170 --> 00:08:54,300 and tell them to hide that frame of theirs so we can call it hide task frame. 128 00:08:57,360 --> 00:09:01,410 We can have an event to let a player know when they've collected money. 129 00:09:01,410 --> 00:09:06,450 So for example, if they find on the map a particular, you know, coin or dollar laying around and 130 00:09:06,450 --> 00:09:10,470 they click it, then we can tell them to display that little money symbol on their screen. 131 00:09:10,470 --> 00:09:13,140 So we could call this collected money. 132 00:09:17,680 --> 00:09:21,040 Another action we may want to give to the players is in the beginning. 133 00:09:21,040 --> 00:09:25,510 So we want to give them an introduction message so we can give them a command for that. 134 00:09:25,510 --> 00:09:27,310 We can call it intro message. 135 00:09:29,730 --> 00:09:34,680 And then another action we'll need is the frame to display when our story is over. 136 00:09:34,680 --> 00:09:38,100 It'll be the outro frame so we can just call it outro frame. 137 00:09:43,670 --> 00:09:50,060 And then the last action we'll need is to let a player know when they have died, basically, or to 138 00:09:50,060 --> 00:09:53,510 display a death message on their screen so we can call it died. 139 00:09:55,110 --> 00:09:59,190 And that's basically, I think, all of the enums we'll need for GUI actions. 140 00:09:59,190 --> 00:10:03,030 And then we want to set a meta table on this enum table. 141 00:10:03,030 --> 00:10:10,530 And inside of this meta table, we'll have an index meta method equal to a function where we get passed 142 00:10:10,530 --> 00:10:12,390 the table itself and a key. 143 00:10:12,390 --> 00:10:18,840 And basically what happens is if we index this enum with a key that does not exist, this index meta 144 00:10:18,840 --> 00:10:20,070 method will get called. 145 00:10:20,070 --> 00:10:26,160 And all we're going to do in here is just create an error and say something like percentage s is not 146 00:10:26,160 --> 00:10:30,000 a valid member of a percentage s. 147 00:10:30,000 --> 00:10:34,620 And then what we're going to do is we're going to format this with the key. 148 00:10:34,620 --> 00:10:36,900 So we can use two string key. 149 00:10:36,900 --> 00:10:40,830 And then for the second directive it's just going to be the name of this script. 150 00:10:40,830 --> 00:10:42,120 So scriptname. 151 00:10:42,270 --> 00:10:47,730 So if we index something in here that doesn't exist, it'll say, you know, whatever key is not a valid 152 00:10:47,730 --> 00:10:49,950 member of GUI actions enum. 153 00:10:49,950 --> 00:10:53,130 And then we'll make sure to return this enum at the very end. 154 00:10:53,460 --> 00:10:59,130 So to show an example of this, what I'm going to do is I'm going to require this module script. 155 00:10:59,130 --> 00:11:08,280 So I'm going to do game dot replicated storage, dot modules dot enums dot gui actions enum. 156 00:11:08,280 --> 00:11:12,000 And what I'm going to do is I'm going to index this table with a key that does not exist. 157 00:11:12,000 --> 00:11:13,230 So something like that. 158 00:11:13,230 --> 00:11:16,530 If I hit enter boom we're going to get. 159 00:11:17,550 --> 00:11:19,080 Oops, we didn't get the right message. 160 00:11:19,080 --> 00:11:22,770 So actually let me like, store this in a variable. 161 00:11:23,460 --> 00:11:26,400 So if we do that, then we're going to get our error. 162 00:11:26,700 --> 00:11:30,510 A f dash DF is not a valid member of GitHub actions. 163 00:11:30,780 --> 00:11:34,920 So it lets us know that hey, you try to access a member that does not exist. 164 00:11:34,920 --> 00:11:37,590 Anyway, back to our player join service. 165 00:11:37,590 --> 00:11:45,000 We can now go ahead and require our GitHub actions enum so we can call this guy actions enum. 166 00:11:46,750 --> 00:11:49,330 Equal to require replicated storage. 167 00:11:49,330 --> 00:11:52,840 Dot modules dot enums dot gui action enum. 168 00:11:52,900 --> 00:11:57,430 The next thing I'm going to do is I'm going to create a variable to store the teleport data that gets 169 00:11:57,430 --> 00:11:58,840 sent to the server. 170 00:11:58,840 --> 00:12:01,570 So we're going to go ahead and call this teleport data. 171 00:12:01,570 --> 00:12:04,480 And we're not going to initialize it with anything just yet. 172 00:12:04,780 --> 00:12:10,540 Some other variables I'm going to create is a number to keep track of how many players are in our game, 173 00:12:10,540 --> 00:12:12,040 which is currently zero. 174 00:12:12,040 --> 00:12:16,630 We're going to have a number to represent the expected number of players we should have in the game. 175 00:12:16,630 --> 00:12:21,550 So when we get players teleported here, they're going to get data sent with them to tell the server 176 00:12:21,550 --> 00:12:22,870 how many players to expect. 177 00:12:22,870 --> 00:12:25,690 So expected players currently is equal to zero. 178 00:12:26,510 --> 00:12:28,070 Uh, we're also going to have a variable. 179 00:12:28,070 --> 00:12:29,750 I'm going to call it time elapsed. 180 00:12:29,750 --> 00:12:34,970 And we're going to use this to check, uh, how long it's been since the players have been loading. 181 00:12:34,970 --> 00:12:42,230 So if a player is loading for way too long or if somebody times out or whatever, we don't want to get 182 00:12:42,230 --> 00:12:42,980 stuck. 183 00:12:42,980 --> 00:12:50,480 Basically, if, for example, a server of three people gets teleported to the story, but somehow only 184 00:12:50,480 --> 00:12:55,730 two people make it, but it says we expect three players, we don't want to be stuck in a loop forever, 185 00:12:55,730 --> 00:12:58,190 where we're waiting for a player that's never going to show up. 186 00:12:58,190 --> 00:13:00,710 So we want to make sure we have a timeout in here. 187 00:13:00,710 --> 00:13:05,930 That way we're not stuck in a loop forever, and that way our game isn't loading forever. 188 00:13:06,110 --> 00:13:10,700 And then I'm going to create a table to store all of the players that have been loaded inside of our 189 00:13:10,700 --> 00:13:11,210 game. 190 00:13:11,870 --> 00:13:14,660 And then we're going to create a constant for our game. 191 00:13:14,660 --> 00:13:20,270 And this is going to represent how much money we need or how much rent we owe for our game. 192 00:13:20,270 --> 00:13:23,990 So we could call it rent owed is equal to like $500. 193 00:13:23,990 --> 00:13:28,670 Now you could create a module script and replicated storage to store all of the different settings for 194 00:13:28,670 --> 00:13:29,270 the game. 195 00:13:29,270 --> 00:13:35,750 So for example, if you wanted to independently control how much rent you owe just from one script alone, 196 00:13:35,750 --> 00:13:40,040 then you could create a module script to store all of the universal game settings. 197 00:13:40,040 --> 00:13:42,920 But for now, we're just going to leave it inside of this constant. 198 00:13:43,370 --> 00:13:45,410 Now, some private functions that we're going to need. 199 00:13:45,410 --> 00:13:49,820 One is a function to check whether or not an argument matches a particular type. 200 00:13:49,820 --> 00:13:52,580 So arg matches type. 201 00:13:52,580 --> 00:13:53,960 You remember this function. 202 00:13:53,960 --> 00:13:57,710 We can literally just go back to our original place and just copy it. 203 00:13:57,710 --> 00:14:01,970 So back in our original game, if we go into something like server service, as you can see the functions 204 00:14:01,970 --> 00:14:03,920 right here, we can literally just copy this. 205 00:14:04,780 --> 00:14:07,780 And then back in our main game, we can just paste that right in there. 206 00:14:07,780 --> 00:14:09,460 So that way we don't have to type it out. 207 00:14:09,550 --> 00:14:12,520 Another function we want to have is to start our game. 208 00:14:12,520 --> 00:14:14,110 So we'll just call it start game. 209 00:14:14,110 --> 00:14:20,620 And all this is going to do is use our start game event and fire to whatever other script needs to know 210 00:14:20,620 --> 00:14:22,180 that it's time to start the game. 211 00:14:23,450 --> 00:14:29,570 Um, a function we're going to need is to listen for when a descendant is added. 212 00:14:29,570 --> 00:14:32,210 So we're going to call this on descendant added. 213 00:14:32,210 --> 00:14:33,800 You're going to be like, well, what's this for? 214 00:14:33,800 --> 00:14:38,720 Well, when a player joins a game, we need to set up the collision groups on that player. 215 00:14:42,500 --> 00:14:46,220 And we're going to need one for when a descendant is removed as well. 216 00:14:46,220 --> 00:14:49,790 So that means we're going to have to set up some collision groups as well real quick. 217 00:14:50,390 --> 00:14:54,980 Another function we're going to need is to create the leader stats for a player. 218 00:14:54,980 --> 00:14:58,700 So we can call this function create leader stats. 219 00:14:59,380 --> 00:15:01,030 For a particular player. 220 00:15:01,630 --> 00:15:05,980 And we're also going to need a function to listen for when a character is added to a player. 221 00:15:05,980 --> 00:15:07,810 So on character added. 222 00:15:09,110 --> 00:15:12,380 We're going to want to listen to when a player is added to our game. 223 00:15:12,380 --> 00:15:12,830 So on. 224 00:15:12,830 --> 00:15:13,970 Player added. 225 00:15:14,770 --> 00:15:18,400 And then we're going to want to listen for when a player is being removed from our game. 226 00:15:18,400 --> 00:15:21,730 So we can call this function on player removing. 227 00:15:22,690 --> 00:15:27,760 Okay, so down in our public functions section, what we need to do is we need to have an initialize 228 00:15:27,760 --> 00:15:29,050 function for this service. 229 00:15:29,050 --> 00:15:31,840 So player joined service in it. 230 00:15:32,230 --> 00:15:35,620 And we're also going to need a function to start the service. 231 00:15:36,850 --> 00:15:37,630 Start. 232 00:15:39,230 --> 00:15:40,880 And inside of our initialize function. 233 00:15:40,880 --> 00:15:45,140 What we need to do is that we need to first loop through every single player that's already inside of 234 00:15:45,140 --> 00:15:45,680 our game. 235 00:15:45,680 --> 00:15:50,930 So for every single player and players get players. 236 00:15:51,840 --> 00:15:58,410 What we need to do is we want to use our on player added function and connect it to this particular 237 00:15:58,410 --> 00:15:58,830 player. 238 00:15:58,830 --> 00:16:01,590 So we want to pass a player object to this function. 239 00:16:01,590 --> 00:16:04,980 And then after that we can connect to the player added event. 240 00:16:04,980 --> 00:16:11,670 So players dot player added we want to connect the on player added function to this event as well. 241 00:16:11,670 --> 00:16:16,140 And then we also want to connect to the player's removing event. 242 00:16:16,140 --> 00:16:20,400 So player removing we want to connect our on player removing function. 243 00:16:20,520 --> 00:16:24,720 And then here we also want to listen to our player loaded event. 244 00:16:24,720 --> 00:16:28,800 So on server event we'll just connect a Lambda function to this. 245 00:16:28,800 --> 00:16:30,540 And we'll get passed a player here. 246 00:16:30,540 --> 00:16:34,530 And this is where we'll fill out that loaded players table. 247 00:16:34,530 --> 00:16:37,830 And I think that's all we'll need to do here for now. 248 00:16:37,830 --> 00:16:41,760 So let's go ahead and first fill out our on player added function. 249 00:16:42,120 --> 00:16:46,710 So when a player gets added to our game, what we want to do first of all is we want to increment our 250 00:16:46,710 --> 00:16:48,540 players in game variable. 251 00:16:48,540 --> 00:16:50,430 So plus equal to one. 252 00:16:50,910 --> 00:16:54,840 Then we want to connect our uh character added event. 253 00:16:54,840 --> 00:16:56,640 So player oops. 254 00:16:56,640 --> 00:16:59,910 Let me denote that we get a player pass to this function. 255 00:17:01,420 --> 00:17:06,550 So player character added we want to connect our on character added function. 256 00:17:07,660 --> 00:17:12,130 And then we also want to create the leader board or leader stats for this particular player. 257 00:17:12,490 --> 00:17:16,780 Now remember we created that variable of teleport data. 258 00:17:17,500 --> 00:17:20,560 Um, if teleport data isn't nil. 259 00:17:21,170 --> 00:17:28,400 Then we're just going to return because every single player is going to have teleport data given to 260 00:17:28,400 --> 00:17:32,360 them, and we only want to get the teleport data once. 261 00:17:32,360 --> 00:17:37,220 So what we're going to do is we're going to update teleport data equal to this player. 262 00:17:37,550 --> 00:17:43,460 And this player has a function inside of it called Get join data, which has all of the data that we 263 00:17:43,460 --> 00:17:45,800 pass from the lobby to this server. 264 00:17:46,010 --> 00:17:50,360 And then from that point we can get the table in there, which is our teleport data table. 265 00:17:50,570 --> 00:17:54,770 Now for some reason this player does not have any teleport data with them. 266 00:17:54,770 --> 00:18:00,320 So if not teleport data then all we're going to do is just set expected players to one. 267 00:18:00,320 --> 00:18:04,730 Because for example, if we're testing in studio when a player joins the game, they're not going to 268 00:18:04,730 --> 00:18:06,170 have any teleport data on them. 269 00:18:06,170 --> 00:18:09,770 So we're just going to set the expected players variable to a default of one. 270 00:18:10,450 --> 00:18:15,310 Otherwise, if there is teleport data, then what we need to do is we need to set expected players equal 271 00:18:15,310 --> 00:18:19,060 to that teleport data dot member. 272 00:18:19,060 --> 00:18:20,110 Expected player. 273 00:18:20,110 --> 00:18:25,090 So we created a key in there that stores the number of players that the server should expect to join 274 00:18:25,090 --> 00:18:25,840 the game. 275 00:18:26,020 --> 00:18:26,470 All right. 276 00:18:26,470 --> 00:18:29,620 So now let's go ahead and fill out our on character added function. 277 00:18:30,220 --> 00:18:35,230 So first off what we're going to do in here is we're going to get the character. 278 00:18:35,990 --> 00:18:40,610 And the first thing we actually want to set up for a character is their footsteps. 279 00:18:40,610 --> 00:18:44,390 So my plan is, is that we're going to have footsteps for players. 280 00:18:44,390 --> 00:18:47,750 So that way when they're walking on different surfaces, it'll play a footstep sound. 281 00:18:47,750 --> 00:18:51,110 So we need to go ahead and set up that audio instance here on the server. 282 00:18:51,110 --> 00:18:53,330 So we'll have a section for footsteps. 283 00:18:53,480 --> 00:18:56,750 And all we'll need to do is make a reference to the root part of this player. 284 00:18:56,750 --> 00:18:58,040 So character. 285 00:19:00,190 --> 00:19:03,370 That humanoid brute part. 286 00:19:03,370 --> 00:19:06,700 And what we're going to do is we're going to create a variable called footstep. 287 00:19:06,700 --> 00:19:13,480 Sound is equal to a new sound instance, and we're going to set the parent of this sound instance to 288 00:19:13,480 --> 00:19:14,770 our root part. 289 00:19:14,770 --> 00:19:20,680 But first we need to set the name of this equal to footsteps. 290 00:19:21,640 --> 00:19:26,110 We want to set the volume of the sound instance to something like 0.15. 291 00:19:26,790 --> 00:19:30,840 The footstep sound roll off max distance. 292 00:19:30,840 --> 00:19:32,880 We want to set it to something like 30. 293 00:19:32,970 --> 00:19:41,550 And then for footstep sound dot roll off mode we want to set it to enum dot roll off mode dot inverse 294 00:19:41,550 --> 00:19:42,450 tapered. 295 00:19:42,450 --> 00:19:49,410 And then we want to do footstep sound dot play on remove equal to true. 296 00:19:49,900 --> 00:19:56,080 And then we can set the parent of this footstep sound equal to the root part of the player. 297 00:19:56,580 --> 00:20:01,500 Once we've done that, then what we're going to do is we're going to loop through every single child 298 00:20:01,500 --> 00:20:03,000 of our character. 299 00:20:03,000 --> 00:20:12,840 So what we could do here is for every single child or descendant in our character, so character get 300 00:20:12,840 --> 00:20:14,370 descendants. 301 00:20:14,910 --> 00:20:21,150 What we want to do is we want to call our on descendant added function and pass this child to it. 302 00:20:21,760 --> 00:20:27,040 Otherwise for any other future descendants that are added to the character, we can listen to it using 303 00:20:27,040 --> 00:20:27,670 the character. 304 00:20:27,880 --> 00:20:29,590 Descendant added event. 305 00:20:29,590 --> 00:20:40,030 So descendant added connect our on descendant added function and then when a descendant is removed from 306 00:20:40,030 --> 00:20:50,590 the character, we'll listen to the descendant removing and connect our on descendant removed function. 307 00:20:51,420 --> 00:20:57,750 Because the plan is here is that when we are updating the collision groups for a player, when a tool 308 00:20:57,750 --> 00:21:03,900 gets added to the player's inventory or some specific item, or maybe some kind of cosmetic, whatever 309 00:21:03,900 --> 00:21:09,300 it may be, we want to update the collision group for that particular descendant and set it to a collision 310 00:21:09,300 --> 00:21:14,700 group where it can't collide with other particular things, and then when that descendant gets removed 311 00:21:14,700 --> 00:21:18,660 from the player, maybe it gets put in their backpack or maybe it gets dropped on the ground. 312 00:21:18,660 --> 00:21:23,370 Whatever the case is, then we want to re update the collision group for that item and make it back 313 00:21:23,370 --> 00:21:25,080 to the default collision group. 314 00:21:25,500 --> 00:21:28,710 So that means we're going to have to create several collision groups. 315 00:21:28,710 --> 00:21:30,930 So go ahead and go to your model tab. 316 00:21:30,930 --> 00:21:33,810 And we're going to go ahead and open up a collision Groups. 317 00:21:34,200 --> 00:21:36,240 And let me go ahead and drag this out here. 318 00:21:36,830 --> 00:21:37,940 And resize it. 319 00:21:37,940 --> 00:21:40,160 So it's a little bit easier to read. 320 00:21:40,160 --> 00:21:42,980 And I'm going to add several new groups here. 321 00:21:42,980 --> 00:21:47,330 One new group is going to be for The doors in our game, so I'll just call it door. 322 00:21:47,690 --> 00:21:51,740 Another new collision group we're going to create is for all of the players. 323 00:21:51,740 --> 00:21:53,540 So we're going to call this player. 324 00:21:54,970 --> 00:21:59,950 And then we're going to have a collision group specifically for Squidward. 325 00:22:01,990 --> 00:22:07,870 And then we're going to have a collision group for all of the objects that our squid were can pass through, 326 00:22:07,870 --> 00:22:09,400 but our players can't. 327 00:22:09,400 --> 00:22:15,640 So, for example, let's say our main Squidward guy over here and our story, we're going to have him 328 00:22:15,640 --> 00:22:20,740 walk through this door and down into the basement, but we don't want the players to walk through here. 329 00:22:20,740 --> 00:22:26,050 We have an invisible wall to block this door that Squidward should be able to pass through, but our 330 00:22:26,050 --> 00:22:30,370 players can't be able to pass through, so that means we need to update the collision group on that 331 00:22:30,370 --> 00:22:33,190 particular item with this newer one. 332 00:22:33,190 --> 00:22:40,960 So we're going to add another new collision group, and we're going to call this uh pass for squid. 333 00:22:41,350 --> 00:22:46,600 So once you have filled all of these different collision groups out, what we need to do next is to 334 00:22:46,600 --> 00:22:50,380 edit all of the collisions for a particular collision group. 335 00:22:50,770 --> 00:22:57,190 So for the door collision group, every single, um, collision group except for Squidward should be 336 00:22:57,190 --> 00:22:58,510 able to collide with the door. 337 00:22:58,510 --> 00:23:04,060 So for example, a player should be able to collide with a door, and all the other stupid stuff should 338 00:23:04,060 --> 00:23:08,500 be able to collide with it, but Squidward should be able to pass through doors no problem. 339 00:23:08,500 --> 00:23:09,880 And then inside of pass. 340 00:23:09,880 --> 00:23:10,780 For Squidward. 341 00:23:10,780 --> 00:23:16,210 This also needs to be a collision group that every other thing can collide with it, but our Squidward 342 00:23:16,210 --> 00:23:18,190 shouldn't be able to collide with it. 343 00:23:18,190 --> 00:23:23,050 For the player collision group, our players should be able to collide with everything except other 344 00:23:23,050 --> 00:23:26,320 players, because we don't want players to be stacking on top of each other. 345 00:23:26,860 --> 00:23:31,420 And then for our Squidward collision group, our Squidward should be already updated. 346 00:23:31,420 --> 00:23:32,440 Just like this. 347 00:23:32,440 --> 00:23:37,390 We shouldn't be able to collide with doors, and we shouldn't be able to collide with anything that 348 00:23:37,390 --> 00:23:39,940 has this pass for Squid Collision group. 349 00:23:39,940 --> 00:23:44,440 Now, you shouldn't have to worry about going through all of the doors and stuff in the map to update 350 00:23:44,440 --> 00:23:49,960 it with these different collision groups, because if you actually take a look at our doors, for example, 351 00:23:49,960 --> 00:23:51,670 here's our basement blocking wall. 352 00:23:51,670 --> 00:23:57,130 If you scroll down to the collision group section here, we already have the string in here for our 353 00:23:57,130 --> 00:23:58,720 pass for squid collision group. 354 00:23:58,720 --> 00:24:06,040 So as long as you name your collision group the exact same as I have showed you right here, then you 355 00:24:06,040 --> 00:24:07,300 should be good to go. 356 00:24:07,300 --> 00:24:13,420 So, for example, if you look at this door right here and we pick something random like the door itself, 357 00:24:13,420 --> 00:24:18,310 we should be able to see that the collision group is set to door. 358 00:24:19,170 --> 00:24:21,240 So we should be good to go there. 359 00:24:22,220 --> 00:24:28,190 So back in our prior joint service, what we need to do next, I would assume, is to fill out our en 360 00:24:28,190 --> 00:24:29,750 descendant added function. 361 00:24:30,170 --> 00:24:34,010 So inside of en descendant added we'll get a descendant here. 362 00:24:34,010 --> 00:24:35,540 So descendant. 363 00:24:35,900 --> 00:24:41,360 And what we want to do when a descendant is added on to a character is that we want to check if this 364 00:24:41,360 --> 00:24:42,560 descendant is a base part. 365 00:24:42,560 --> 00:24:46,790 So if a descendant is a base part. 366 00:24:48,780 --> 00:24:55,530 Then what we want to do is we want to set the collision group of this descendant equal to the players 367 00:24:55,530 --> 00:24:58,110 collision group, because it is now part of the player. 368 00:24:58,110 --> 00:25:01,320 And then for the same thing with this descendant remove function. 369 00:25:01,320 --> 00:25:07,350 If the descendant passed to this function is a base part, then we want to set the collision group to 370 00:25:07,350 --> 00:25:09,810 the default collision group, which is just default. 371 00:25:10,550 --> 00:25:10,970 Okay. 372 00:25:10,970 --> 00:25:15,440 So the next function that we could go ahead and fill out is our on player removing function. 373 00:25:15,680 --> 00:25:21,050 So when a player is removed we'll get a player passed to this function. 374 00:25:22,080 --> 00:25:27,120 And what we want to do is we want to set our players in game variable minus equal one. 375 00:25:27,120 --> 00:25:31,800 And then we also want to set our expected players variable minus equal one. 376 00:25:32,430 --> 00:25:38,790 And then what we're going to do is we're going to check whether or not this player was a loaded player. 377 00:25:38,790 --> 00:25:44,490 So we're going to get an index from our table dot find function inside of our loaded players table. 378 00:25:44,490 --> 00:25:46,470 And we're going to look for this particular player. 379 00:25:46,470 --> 00:25:50,100 If this player is inside of this table then we're going to remove them. 380 00:25:50,100 --> 00:25:55,800 So if I then table dot remove from loaded players. 381 00:25:56,370 --> 00:26:01,650 At this particular index, because now what we could do is we could fill out our player loaded event 382 00:26:01,650 --> 00:26:02,640 function here. 383 00:26:02,640 --> 00:26:08,490 So when a player tells us that they've been loaded into the game, then what we're going to do is insert 384 00:26:08,490 --> 00:26:11,820 them into the loaded players table. 385 00:26:11,910 --> 00:26:13,500 So loaded player's player. 386 00:26:13,770 --> 00:26:19,140 Now, since an exploiter could rapid fire this event here and fill up the table with a whole bunch of 387 00:26:19,140 --> 00:26:23,400 players, we want to make sure that they're not already inside of our loaded players table. 388 00:26:23,400 --> 00:26:31,050 So if not table dot find inside of loaded players this player, then we can go ahead and insert them 389 00:26:31,050 --> 00:26:32,670 into the loaded players table. 390 00:26:33,120 --> 00:26:37,170 Otherwise if they're already inside of there then we don't need to do anything else. 391 00:26:38,350 --> 00:26:42,430 The next function we can go ahead and fill out is our create Leaderstats function. 392 00:26:43,220 --> 00:26:47,660 So what we're going to do in here is we're going to create a new folder and we're going to call it leader 393 00:26:47,660 --> 00:26:48,500 stats. 394 00:26:48,950 --> 00:26:51,560 So instance dot new folder. 395 00:26:52,130 --> 00:26:58,820 And to create a leaderboard the name of this folder has to be leader stats exactly like this. 396 00:27:00,780 --> 00:27:05,400 And then we want to set the parent of this leader stats equal to the player object. 397 00:27:07,110 --> 00:27:10,290 And we can go ahead and denote this as a player as well up here. 398 00:27:11,070 --> 00:27:17,700 And then what we want to do is I want to create two int values inside of our leaderboard. 399 00:27:17,700 --> 00:27:22,170 One is going to be for the number of deaths of this player, and the other one is going to be for how 400 00:27:22,170 --> 00:27:23,460 much money they have. 401 00:27:23,460 --> 00:27:29,340 So we're going to call one of these variables money which is equal to instance dot new int value. 402 00:27:31,850 --> 00:27:35,960 And for this value, we're just going to set the name equal to money. 403 00:27:37,560 --> 00:27:40,410 We're going to set the value. 404 00:27:41,060 --> 00:27:42,530 Equal to zero. 405 00:27:42,530 --> 00:27:46,940 And we're going to set the parent equal to our Leaderstats folder. 406 00:27:47,090 --> 00:27:49,430 And then we're going to do the same thing with deaths. 407 00:27:49,430 --> 00:27:51,350 So instance dot new int value. 408 00:27:52,130 --> 00:27:55,670 We're going to set deaths dot name equal to deaths. 409 00:27:56,220 --> 00:28:03,570 Deaths, dot value is equal to zero and then deaths dot parent is equal to our leader stats folder. 410 00:28:03,810 --> 00:28:09,660 And then what we're going to do next is we're going to listen to when our money value changes. 411 00:28:09,660 --> 00:28:16,290 So on our money int value we're going to use our get property change signal function and listen for 412 00:28:16,290 --> 00:28:19,500 when the value changes in our money int value. 413 00:28:19,500 --> 00:28:22,560 And when it does we want to connect a lambda function to this. 414 00:28:22,920 --> 00:28:28,110 And what we're going to do is we're going to check if the money dot value. 415 00:28:29,190 --> 00:28:34,890 Uh, is greater than or equal to the rent owed constant. 416 00:28:35,250 --> 00:28:42,360 If it is, then what we could do is we could fire to this particular player that, hey, they fulfilled 417 00:28:42,360 --> 00:28:49,350 one of the objectives, which was to, you know, uh, get enough rent so we can fire to this particular 418 00:28:49,350 --> 00:28:55,440 client here or this player and give them a UI actions enum of like objective fulfilled. 419 00:28:55,440 --> 00:29:00,600 And then we can pass them a table with the name of the particular objective that they fulfilled. 420 00:29:00,600 --> 00:29:02,520 So we can create a key in here. 421 00:29:02,520 --> 00:29:08,610 We'll just call this fulfilled objective name and we'll just set it equal to money. 422 00:29:10,000 --> 00:29:12,790 And we're going to go ahead and script the guy later on. 423 00:29:12,790 --> 00:29:15,670 But this is going to be what we're going to be putting here for now. 424 00:29:16,240 --> 00:29:21,670 Okay, now, the last thing we need to fill out inside of our player join service is our start function. 425 00:29:21,670 --> 00:29:27,730 So what we're going to do in here is I'm going to spawn a new thread. 426 00:29:27,730 --> 00:29:31,030 So we're going to use task Dot. 427 00:29:31,030 --> 00:29:35,380 And I guess we could use defer because we don't need it to run instantaneously. 428 00:29:36,520 --> 00:29:41,500 And again, we have to spawn this in a new thread because I'm going to be putting while loops in here, 429 00:29:41,500 --> 00:29:47,650 and we do not want to impede our loader on the server because it's going to jump into this function. 430 00:29:47,650 --> 00:29:51,550 And if there's anything in here that's going to yield, we want to make sure that it's yielding in a 431 00:29:51,550 --> 00:29:52,420 separate thread. 432 00:29:52,420 --> 00:29:59,140 So what I'm going to do in here is I'm going to first check if the number of players in our game. 433 00:29:59,140 --> 00:30:01,600 So get players. 434 00:30:01,600 --> 00:30:07,660 If this is equal to zero somehow, then we're going to wait for players to be actually added into our 435 00:30:07,660 --> 00:30:08,200 game. 436 00:30:08,200 --> 00:30:11,920 So we're going to go ahead and wait for the first player to join. 437 00:30:13,910 --> 00:30:17,720 Once the first player is actually in the game, then we're going to do is we're going to create a while 438 00:30:17,720 --> 00:30:18,140 loop. 439 00:30:18,140 --> 00:30:28,970 So while players in game is less than the expected players, what we're going to do is we're just going 440 00:30:28,970 --> 00:30:30,470 to wait for one second. 441 00:30:31,010 --> 00:30:38,630 We're going to set time elapsed plus equal one, and then we're going to check if time elapsed becomes 442 00:30:38,630 --> 00:30:41,000 greater than something like 60s. 443 00:30:41,000 --> 00:30:43,880 And if it does, then we're just going to break out of this loop. 444 00:30:44,300 --> 00:30:49,220 So basically, before we even start checking whether or not the number of loaded players in our game 445 00:30:49,220 --> 00:30:55,520 is equal to the number of players in our game, we actually want to verify, first of all, that all 446 00:30:55,520 --> 00:30:57,680 of our players have actually joined the game. 447 00:30:57,680 --> 00:30:59,900 So that's what we're going to use this while loop for. 448 00:30:59,900 --> 00:31:04,100 Once this while loop ends, then we can just set time elapsed back to zero. 449 00:31:04,100 --> 00:31:09,350 And then we're going to wait for one second because then afterwards what we're going to do is we're 450 00:31:09,350 --> 00:31:10,790 going to spawn another while loop. 451 00:31:10,790 --> 00:31:21,620 So while uh, the number of loaded players is less than the players in our game, we're going to do 452 00:31:21,620 --> 00:31:26,060 is we're going to set time elapsed equal to plus equal one. 453 00:31:27,590 --> 00:31:34,160 And we're also going to check if time elapsed becomes greater than or equal to 100 and 80s. 454 00:31:34,160 --> 00:31:41,450 So if 100 and 80s goes by and still not all of the players have loaded into the game yet, well then 455 00:31:41,450 --> 00:31:42,650 something wrong is going on. 456 00:31:42,650 --> 00:31:49,070 So what we're going to do is we're going to loop through every single player and players get players. 457 00:31:50,460 --> 00:31:53,580 We're going to see if this player is not within our loaded players table. 458 00:31:53,580 --> 00:32:00,720 So if table dot find loaded players player, then we're just going to continue looping. 459 00:32:00,720 --> 00:32:04,950 Otherwise, if this particular player is not within the loaded players table then we're just going to 460 00:32:04,950 --> 00:32:05,370 kick them. 461 00:32:05,370 --> 00:32:13,470 So player kick and we're just going to give a message like you took too long to load into the game because 462 00:32:13,470 --> 00:32:16,740 again, the game isn't going to start until all the players have loaded. 463 00:32:16,740 --> 00:32:21,090 But if for some reason some players taking way too stinking long, then we're just going to kick them 464 00:32:21,090 --> 00:32:23,970 because we don't want to ruin the experience for other players. 465 00:32:23,970 --> 00:32:28,380 And since we're running a while loop here, we also need to make sure to yield for one second inside 466 00:32:28,380 --> 00:32:28,860 of it. 467 00:32:29,460 --> 00:32:34,890 And then once all of this is done, once we have verified that the number of players on our game reach, 468 00:32:35,160 --> 00:32:40,500 uh, reaches the expected players and that all of the players have loaded, then what we could do is 469 00:32:40,500 --> 00:32:47,280 we can call our start game function and let the server know that it's time to start our horror game. 470 00:32:48,220 --> 00:32:52,180 And I'm pretty sure that's all we need to do in here for now, actually, so we can go ahead and test 471 00:32:52,180 --> 00:32:52,840 that out here. 472 00:32:52,840 --> 00:32:54,190 So if we hit play. 473 00:32:55,910 --> 00:33:00,740 But it doesn't appear that our loop is quite working for the waiting for players text. 474 00:33:00,740 --> 00:33:02,990 So let's go ahead and take a look at that real quick. 475 00:33:03,050 --> 00:33:05,870 So inside of our loading UI. 476 00:33:09,470 --> 00:33:11,360 Or it could be that. 477 00:33:13,040 --> 00:33:13,730 Yeah. 478 00:33:13,730 --> 00:33:18,620 Uh, we should actually delete these from the workspace. 479 00:33:18,620 --> 00:33:21,680 First of all, I think that's definitely conflicting there. 480 00:33:22,760 --> 00:33:31,820 Oh, well, we forgot to do here actually is we forgot to change this condition right here. 481 00:33:31,820 --> 00:33:37,040 So what we need to do instead is we need to replace this with a variable like players. 482 00:33:37,040 --> 00:33:37,670 Ready. 483 00:33:37,670 --> 00:33:39,830 So we'll create it at the top here. 484 00:33:39,830 --> 00:33:42,410 So I'll just create a variable called players. 485 00:33:42,410 --> 00:33:43,130 Ready. 486 00:33:43,820 --> 00:33:45,110 Set it to false for now. 487 00:33:45,900 --> 00:33:51,120 So once all of the players are ready and once this event gets fired, we can set players ready equal 488 00:33:51,120 --> 00:33:52,050 to true. 489 00:33:54,000 --> 00:33:54,450 Okay. 490 00:33:54,570 --> 00:33:55,050 Perfect. 491 00:33:55,080 --> 00:33:58,800 Now our loading screen is telling us that we are waiting for players. 492 00:33:58,830 --> 00:34:06,270 Now, this guy is not going to fade out until that event gets fired back to our client. 493 00:34:06,270 --> 00:34:09,120 And we're going to have to do that from a different service. 494 00:34:09,120 --> 00:34:14,610 So when our player joins service, notifies the other service that it's time to start the game, then 495 00:34:14,610 --> 00:34:19,320 that service is going to fire to all of the different players that, hey, it's time to go. 496 00:34:19,320 --> 00:34:24,600 It'll tell them what to do, it'll tell them to display the intro message and all of the good stuff 497 00:34:24,600 --> 00:34:25,440 like that. 498 00:34:26,010 --> 00:34:30,060 Otherwise, we've got everything that we needed to complete in this lecture done for now, and I'll 499 00:34:30,060 --> 00:34:31,560 go ahead and see you in the next one.